<script setup lang="ts">
import { ref, reactive } from "vue";
import type { Editor, EditorConfiguration } from "codemirror";
import Codemirror from "codemirror-editor-vue3";

// ★ Java 语法高亮：引入 clike 模式（包含 Java）
import "codemirror/mode/clike/clike.js";

// ★ 自动补全提示模块
import "codemirror/addon/hint/show-hint.js";
import "codemirror/addon/hint/show-hint.css";

// ★ 括号匹配
import "codemirror/addon/edit/matchbrackets.js";

// ★ 自动补全括号与引号
import "codemirror/addon/edit/closebrackets.js";

// ★ 代码折叠
import "codemirror/addon/fold/foldcode.js";
import "codemirror/addon/fold/foldgutter.js";
import "codemirror/addon/fold/brace-fold.js";
import "codemirror/addon/fold/foldgutter.css";

// ★ 代码错误检查（Lint）插件
import "codemirror/addon/lint/lint.js";
import "codemirror/addon/lint/lint.css";

// ★ 引入第三方 Java 解析器用于错误检查
import { parse } from "java-parser";

// ★ 同时需要导入 CodeMirror 核心对象以注册辅助函数
import CodeMirror from "codemirror";
import {useProblemCodeStore} from "@/stores/problem-code.ts";

// ---------- 注册 Java Lint 辅助函数 ----------
// 当解析出错时，java-parser 会抛出错误对象，其中包含 location 信息
CodeMirror.registerHelper("lint", "text/x-java", function(text:string) {
  const found = [];
  try {
    parse(text);
  } catch (e: any) {
    if (e && e.location) {
      // 注意：java-parser 的行号从 1 开始，而 CodeMirror 的行号从 0 开始
      const line = e.location.start.line - 1;
      const ch = e.location.start.column;
      found.push({
        from: CodeMirror.Pos(line, ch),
        to: CodeMirror.Pos(line, ch + 1),
        message: e.message,
        severity: "error"
      });
    } else {
      // 如果没有 location 信息，标记在文件开头
      found.push({
        from: CodeMirror.Pos(0, 0),
        to: CodeMirror.Pos(0, 1),
        message: e.message || "语法错误",
        severity: "error"
      });
    }
  }
  return found;
});

// ---------- 注册自定义 Java 自动补全提示 ----------
const javaKeywords = [
  "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class",
  "const", "continue", "default", "do", "double", "else", "enum", "extends", "final",
  "finally", "float", "for", "if", "implements", "import", "instanceof", "int", "interface",
  "long", "native", "new", "package", "private", "protected", "public", "return", "short",
  "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws",
  "transient", "try", "void", "volatile", "while", "String"
];

CodeMirror.registerHelper("hint", "java", function(editor:any) {
  const cur = editor.getCursor();
  const token = editor.getTokenAt(cur);
  const start = token.start;
  const end = cur.ch;
  const word = token.string.slice(0, end - start);
  const list = javaKeywords.filter(kw => kw.startsWith(word));
  return {
    list,
    from: CodeMirror.Pos(cur.line, start),
    to: CodeMirror.Pos(cur.line, end)
  };
});

// ---------- 初始化示例代码 ----------
const code = ref('');

// ---------- 配置 CodeMirror 编辑器选项 ----------
const cmOptions: EditorConfiguration = reactive({
  mode: "text/x-java", // ★ Java 语法高亮模式
  theme: "default",
  readOnly: false,
  lineNumbers: true,
  lineWrapping: true,
  gutters: ["CodeMirror-lint-markers", "CodeMirror-foldgutter"], // 显示错误标记和折叠区域
  lint: true,                // ★ 启用 Lint 功能
  matchBrackets: true,       // 括号匹配
  autoCloseBrackets: true,   // 自动补全括号与引号
  extraKeys: {
    "Ctrl-L": "autocomplete",               // 自动补全触发（使用自定义 Java 补全助手）
    "Ctrl-Q": (cm) => cm.foldCode(cm.getCursor()), // 代码折叠
    "Shift-Alt-F": () => formatCode()              // 格式化代码（示例）
  },
  indentUnit: 4,        // 每次缩进 4 个空格
  tabSize: 4,           // Tab 键显示 4 个空格
  indentWithTabs: false, // 使用空格而非 Tab 键
});


const cminstance = ref<Editor | null>(null);
const onReady = (cm: Editor) => {
  cminstance.value = cm;
};

function setCode(newCode: string) {
  code.value = newCode;
  if (cminstance.value) {
    cminstance.value.setValue(newCode);
  }
}

// ---------- 示例：格式化代码（格式化逻辑需自行实现或集成第三方格式化库） ----------
const formatCode = () => {
  if (cminstance.value) {
    try {
      const currentCode = cminstance.value.getValue();
      // 这里只作为示例，你可以调用第三方 Java 格式化库进行代码格式化
      console.log("格式化代码触发，当前代码：", currentCode);
    } catch (error) {
      console.error("格式化代码时出错:", error);
    }
  }
};

defineExpose({
  setCode,
  code
})
</script>

<template>
  <Codemirror
      v-model:value="code"
      :options="cmOptions"
      height="100%"
      width="100%"
      class="cm-component"
      :border="true"
      @ready="onReady"
  />
</template>

<style scoped lang="scss">

</style>